<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Sudoku Solver</title>
  <link rel="stylesheet" href="https://unpkg.com/poplar-css@latest/dist/poplar.css">
  <style>
    .puzzle { display: grid; gap: 10px; grid-template-columns: auto 1fr; grid-template-rows: auto auto 1fr; }
    .row:nth-child(3n):not(:last-child) { border-bottom: 2px solid #333; }
    .column:nth-child(3n):not(:last-child) { border-right: 2px solid #333; }
    .cell { box-sizing: border-box; height: 24px; width: 24px; }
  </style>
</head>
<body>

  <div id="root"></div>

  <script src="sudoku.js"></script>
  <script src="puzzles.js"></script>
  <script>
    // puzzles.forEach(item => console.log(new Sudoku(item)))
  </script>
  <script src="https://unpkg.com/react/umd/react.development.js" crossorigin></script>
  <script src="https://unpkg.com/react-dom/umd/react-dom.development.js" crossorigin></script>
  <script src="https://unpkg.com/babel-standalone/babel.min.js"></script>
  <script type="text/babel">
    const { Fragment, useState, useEffect, useCallback } = React

    const App = () => {
      const [lock, setLock] = useState(false)
      const [base, setBase] = useState(puzzles[5])
      const [grid, setGrid] = useState(() => {
        return Array(9).fill('').map(() => Array(9).fill(0))
      })

      const updateCellValue = (i, j, v) => {
        if (!lock) {
          base[i][j] = Number(v)
          setBase(base.slice())
        }
      }

      const solution = useCallback(() => {
        if (lock) return
        const res = new Sudoku(base)
        console.log(res)
        if (res.valueCount === 81) {
          setLock(true)
          setGrid(res.solution)
        } else if (res.errorMessage) {
          window.alert(res.errorMessage)
        }
      }, [lock, base])

      const reset = useCallback(() => {
        setLock(false)
        setBase(Array(9).fill('').map(() => Array(9).fill(0)))
      }, [])

      return (
        <div className="puzzle text-xs">
          <div className="flex-column">
            {(lock ? grid : base).map((r, i) => (
              <div key={i} className="row flex">
                {r.map((c, j) => (
                  <div key={j} className="column">
                    <input
                      className="cell text-center"
                      disabled={lock && base[i][j] && base[i][j] === c}
                      value={(c && !Array.isArray(c)) ? c : ''}
                      maxLength="1"
                      onChange={e => updateCellValue(i, j, e.currentTarget.value)}
                    />
                  </div>
                ))}
              </div>
            ))}
          </div>
          <div></div>

          <button className="button-black button-sm radius-sm" onClick={solution}>解题</button>
          <div></div>

          <button className="button-white button-sm radius-sm" onClick={reset}>重置</button>
          <div></div>
        </div>
      )
    }

    ReactDOM.render(<App />, document.querySelector('#root'))
  </script>

</body>
</html>